// Promise
// 设置状态的枚举
const STATUS = {
    PENDING: 'pending',
    SUCESS: 'sucess',
    FAIL: 'fail',
}
class MyPromise {
    // 构造函数
    constructor(executor) {
        // 执行器
        try {
            executor(this.resolve, this.reject)
        } catch (e) {
            this.reject(e)
        }
    }
    // 默认状态为等待
     status = STATUS.PENDING;
    //成功之后的值
     value = undefined;
     //失败的原因
     reason = undefined;
     //成功之后的回调
     sucessfullCallback = [];
     //失败之后的回调
     failedCallback = [];
    // resolve为成功之后把等待状态判断为成功并保存值的函数
    resolve = (_value) => {
        // 如果不是等待状态不向下执行
        if (this.status !== STATUS.PENDING) { return;}
        //设置状态
        this.status = STATUS.SUCESS;
        // 成功之后的值
        this.value = _value;
        // 把sucessfullCallback的回调执行完毕
        while(this.sucessfullCallback.length) this.sucessfullCallback.shift()()
    }
    // reject为成功之后把等待状态判断为成功并保存值的函数
    reject = (_reason) => {
        // 如果不是等待状态不向下执行
        if (this.status !== STATUS.PENDING) { return;}
        //设置状态
        this.status = STATUS.FAIL;
        // 设置失败的原因
        this.reason = _reason
        // 把failedCallback的回调执行完毕
        while(this.failedCallback.length) this.failedCallback.shift()()
    }
    // 链式调用
    then = function (sucessfullCallback, failedCallback) {
        // 参数可选
        sucessfullCallback = sucessfullCallback ? sucessfullCallback : value => value;
        // 参数可选
        failedCallback = failedCallback ? failedCallback: reason => { throw reason };
        let promsie2 = new MyPromise((resolve, reject) => {
                try {
                    // 返回新的promise的this指针
                    // console.log('that.status',this.status)
                    console.log('this.status',this.status)

                    // 根据当前状态执行
                    switch (this.status) {
                        case STATUS.SUCESS: {
        
                                setTimeout(
                                    () => {
                                        try {
                                            resolvePromise(promsie2, sucessfullCallback(this.value),resolve,reject)
                                        }
                                        catch(e) {
                                            reject(e)
                                        }
                                    },0)
                            break;
                        }
                        case STATUS.FAIL: {
                            setTimeout( () => {
                            try {
                               resolvePromise(promsie2, failedCallback(this.reason),resolve,reject)
                            } catch (e) {
                                reject(e)
                            }},0)
                        
                            break;
                        }
                        default: {
                            this.sucessfullCallback.push( () => {
                                setTimeout(() =>{
                                try {
                                    resolvePromise(promsie2, sucessfullCallback(this.value),resolve,reject)
                                } catch (e) {
                                    reject(e)
                                }},0)
                            });
                            this.failedCallback.push( () => {
                                setTimeout( () =>{
                                try {
                                    resolvePromise(promsie2, failedCallback(this.reason),resolve,reject)
                                } catch (e) {
                                    reject(e)
                                }},0)
                            })
                        }
                    }
                } catch (e) {
                    throw e
                }
            }
        )
        return promsie2;
    }

    // 无论结果如何都进行回调
    finally (callback) {
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value);
        }, reason => {
            return MyPromise.resolve(callback()).then(() => { throw reason })
        })
    }
    // 失败的结果
    catch (failCallback) {
        return this.then(undefined, failCallback)
    }

    static all (array) {
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            function addData (key, value) {
                result[key] = value;
                index++;
                if (index === array.length) {
                    resolve(result);
                }
            }
            for (let i = 0; i < array.length; i++) {
                let current = array[i];
                if (current instanceof MyPromise) {
                    // promise 对象
                    current.then(value => addData(i, value), reason => reject(reason))
                }else {
                    // 普通值
                    addData(i, array[i]);
                }
            }
        })
    }
    static resolve (value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
    }

}
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
 const resolvePromise = function(newPromise,resultCallback,resolve, reject) {
    //  console.log('resultCallback', resultCallback);
    // 如果是函数 就抛出问题
    if (newPromise === resultCallback) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}
    // 判断是promise类型
    if (resultCallback instanceof MyPromise) {
        resultCallback.then(resolve,reject)
    } else {
        resolve(resultCallback)
    }
}

module.exports = MyPromise;
